import appConfig from '@/utils/appConfig';
import request from '@/utils/request';
import Taro, { useDidShow } from '@tarojs/taro';
import { useRequest } from 'ahooks';
import { createGlobalStore } from 'hox';
import useAwaitAsync from '../hook/useAwaitAsync';
import { PlatformEnum } from '@/utils/enum';
import { useInitStore } from './initStore';
import { useEffect, useState } from 'react';
export type PositionType = {
    longitude: number;
    latitude: number;
};

export type PositionResultType = PositionType | false;
const isH5 = process.env.TARO_ENV === 'h5';
const defaultPosition = false;
const POSITION_STORAGE_KEY = 'persisted_position';
const CITY_STORAGE_KEY = 'persisted_city';
// 获取存储的位置信息 - 只在H5环境下使用sessionStorage
const getStoredPosition = async (): Promise<PositionResultType> => {
    if (!isH5) return defaultPosition;

    try {
        const stored = sessionStorage.getItem(POSITION_STORAGE_KEY);
        return stored ? JSON.parse(stored) : defaultPosition;
    } catch (error) {
        return defaultPosition;
    }
}


// 存储位置信息 - 只在H5环境下使用sessionStorage
const storePosition = async (position: PositionResultType) => {
    if (!isH5) return;

    if (position) {
        sessionStorage.setItem(POSITION_STORAGE_KEY, JSON.stringify(position));
    } else {
        sessionStorage.removeItem(POSITION_STORAGE_KEY);
    }
};

// 存储城市信息 - 只在H5环境下使用sessionStorage
const storeCity = async (city: City.List | null) => {
    if (!isH5) return;

    if (city) {
        sessionStorage.setItem(CITY_STORAGE_KEY, JSON.stringify(city));
    } else {
        sessionStorage.removeItem(CITY_STORAGE_KEY);
    }
};

// 获取存储的城市信息 - 只在H5环境下使用sessionStorage
const getStoredCity = async (): Promise<City.List | null> => {
    if (!isH5) return null;

    try {
        const stored = sessionStorage.getItem(CITY_STORAGE_KEY);
        return stored ? JSON.parse(stored) : null;
    } catch (error) {
        return null;
    }
};



const authGuideLocation = async () => {
    const getSystemInfo = () => {
        return new Promise<Taro.getSystemInfo.Result>((resolve, reject) => {
            Taro.getSystemInfo({
                success: resolve,
                fail: reject,
            });
        });
    };
    const getSetting = () => {
        return new Promise<Taro.getSetting.SuccessCallbackResult>((resolve, reject) => {
            if (Taro.getEnv() === Taro.ENV_TYPE.WEAPP) {
                Taro.getSetting({
                    success: resolve,
                    fail: reject,
                });
            }
        });
    };
    const openSetting = () => {
        return new Promise<Taro.openSetting.SuccessCallbackResult>((resolve, reject) => {
            Taro.openSetting({
                success: resolve,
                fail: reject,
            });
        });
    };
    const alert = (content: string) => {
        return new Promise((resolve, reject) => {
            Taro.showModal({
                title: '提示',
                content,
                success: (r) => {
                    if (r.confirm) {
                        resolve(true);
                    } else {
                        reject();
                    }
                },
            });
        });
    };
    // 若用户未开启系统定位或未授权应用使用定位
    const showAuthGuideIfNeeded = async () => {
        // 获取用户是否开启系统定位及授权应用使用定位
        const { locationEnabled, locationAuthorized } = await getSystemInfo();
        const systemLocationEnabled = !!(locationEnabled && locationAuthorized);
        // return true
        if (!systemLocationEnabled) {
            if (process.env.TARO_ENV === 'alipay') {
                if (!locationAuthorized) {
                    my.showAuthGuide({ authType: 'LBS' });
                    return false;
                }
            }
            await alert('请开启手机定位权限，否则无法提供优质使用体验');
            return false;
        } else return true;
    };
    // 获取用户是否授权过当前应用使用定位
    const authLocationKey = (function () {
        if (process.env.TARO_ENV === 'weapp') {
            return 'scope.userLocation';
        } else return 'location';
    })();
    const isLocationMPAuthorized = async () => {
        const { authSetting } = await getSetting();
        const applicationLocationEnabled =
            authSetting[authLocationKey] === undefined || authSetting[authLocationKey];
        // eslint-disable-next-line no-console
        return applicationLocationEnabled;
    };
    // 若用户未授权当前应用使用定位，则引导用户跳转至设置页开启定位权限
    const requestLocationPermission = async () => {
        await alert('请开启小程序地理位置权限，否则无法提供优质使用体验');
        // 这里淘宝小程序无法取到修改后的权限值，所以依然返回 false
        const openSettingInfo = await openSetting();
        return openSettingInfo.authSetting[authLocationKey];
    };
    try {
        if (!(await showAuthGuideIfNeeded())) {
            return false;
        }
        if (await isLocationMPAuthorized()) {
            return true;
        }
        if (await requestLocationPermission()) {
            return true;
        }
        return false;
    } catch (error) {
        return false;
    }
};

function getPosition(): Promise<PositionResultType> {
    return new Promise(async (resolve) => {
        const storedPosition = await getStoredPosition();
        if (storedPosition) {
            resolve(storedPosition);
            return;
        }

        const callback = async () => {
            Taro.getLocation({
                type: 'gcj02',
                isHighAccuracy: process.env.TARO_ENV !== 'tt',
                success: (res) => {
                    if (res.latitude && res.longitude) {
                        const position: PositionType = {
                            latitude: res.latitude,
                            longitude: res.longitude,
                        };
                        storePosition(position); // 存储获取到的位置
                        resolve(position);
                    } else resolve(defaultPosition);
                },
                fail: async () => {
                    resolve(defaultPosition);
                },
                complete: () => {
                    resolve(defaultPosition);
                },
            });
        };
        const getLoad = async () => {
            const loadScript = (): Promise<any> => {
                return new Promise(function (resolve, reject) {
                    var script = document.createElement('script');
                    script.type = 'text/javascript';
                    script.src =
                        'https://apis.map.qq.com/tools/geolocation/min?key=65FBZ-7QBCT-3G7XW-V3VXF-PTNZQ-C6F44&referer=localLife';
                    script.onerror = reject;
                    script.onload = resolve;
                    document.head.appendChild(script);
                });
            };
            await loadScript();
            if (window.qq) {
                const geolocation = new window.qq.maps.Geolocation(
                    '65FBZ-7QBCT-3G7XW-V3VXF-PTNZQ-C6F44', // 自行配置 参考链接  https://lbs.qq.com/service/webService/webServiceGuide/position/location;
                    'localLife'
                );
                geolocation.getLocation(
                    (res: any) => {
                        if (res.lat && res.lng) {
                            const position: PositionType = {
                                latitude: res.lat,
                                longitude: res.lng,
                            };
                            resolve(position);
                        } else {
                            resolve(defaultPosition);
                        }
                    },
                    () => {
                        resolve(defaultPosition);
                    },
                    {
                        timeout: 10000,
                        failTipFlag: true,
                    }
                );
            }
        };
        if (process.env.TARO_ENV === 'h5') {
            // H5（普通浏览器）环境
            if (appConfig.appPlatformType === PlatformEnum.H5) {
                // 链接中存在 坐标则自动赋值经纬度
                if (Taro.getStorageSync('Location')) {
                    const obj = JSON.parse(Taro.getStorageSync('Location'));
                    const position: PositionType = { latitude: obj.lat, longitude: obj.lng };
                    resolve(position);
                    return;
                }
                // 腾讯相关api注入成功则 根据浏览器 自动 获取定位信息
                getLoad();
                return;
            }
            // 微信环境则自动发起定位请求，用户可手动定位
            if (appConfig.appPlatformType === PlatformEnum.WeChatPub) {
                if (typeof window !== 'undefined' && (window as any).wx && (window as any).wx !== undefined) {
                    (window as any).wx.ready(() => callback());
                } else {
                    getLoad();
                }

                return;
            }
        } else {
            // 小程序环境
            if (process.env.TARO_ENV === 'weapp') {
                const res = await authGuideLocation();
                if (!res) return resolve(defaultPosition);
                callback();
                return
            }
            if (process.env.TARO_ENV === 'tt') {
                callback();
                return
                // return resolve()
            }
        }
    });
}

/**
 * @description 坐标获取当前城市 - 电影
 */
async function GetCurrentMovieCity(params: PositionType): Promise<City.List> {
    // 先从缓存读取城市
    const storedCity = await getStoredCity();
    if (storedCity) {
        return storedCity;
    }
    const city = await request.get('/api/Movie/GetCurrentMovieCity', { params });
    await storeCity(city); // 存储获取到的城市
    return city;



}

export const [useCityStore, getCityStore] = createGlobalStore(() => {
    const { initReady, awaitBeforeInit } = useInitStore();
    const [isReady, setIsReady] = useState(false); // 添加 isReady 状态

    useEffect(() => {
        // 初始化时从存储加载数据
        const loadInitialData = async () => {
            try {
                // 加载位置信息
                const storedPosition = await getStoredPosition();
                if (storedPosition) {
                    getPositionApi.mutate(storedPosition);
                }

                // 加载城市信息
                const storedCity = await getStoredCity();
                if (storedCity) {
                    getCurrentMovieCityApi.mutate(storedCity);
                }
            } catch (error) {
                console.error('Failed to load initial location data', error);
            } finally {
                setIsReady(true); // 标记初始化完成
            }
        };

        loadInitialData();
    }, []);

    const getPositionApi = useRequest(async () => {
        await awaitBeforeInit();

        // 先从缓存读取位置
        try {
            const { data: storedPosition } = await Taro.getStorage({ key: POSITION_STORAGE_KEY });
            if (storedPosition) return storedPosition;
        } catch (error) {
            console.log('No stored position found');
        }

        // 获取新位置
        let position: PositionResultType;
        if (appConfig.getPosition) {
            position = await appConfig.getPosition(getPosition);
        } else {
            position = await getPosition();
        }

        // 存储位置
        if (position) {
            await Taro.setStorage({ key: POSITION_STORAGE_KEY, data: position });
        }

        return position;
    }, {
        onError: () => {
            Taro.removeStorage({ key: POSITION_STORAGE_KEY });
        }
    });

    useDidShow(() => {
        if (!getPositionApi.loading && !getPositionApi.data) {
            getPositionApi.run();
        }
    });

    const { awaitAsync: awaitPosition } = useAwaitAsync<PositionResultType>(
        getPositionApi.data,
        (data) => data !== undefined
    );

    const getCurrentMovieCityApi = useRequest(
        async () => {
            if (!getPositionApi.data) return null;

            // 先从缓存读取城市
            try {
                const { data: storedCity } = await Taro.getStorage({ key: CITY_STORAGE_KEY });
                if (storedCity) return storedCity;
            } catch (error) {
                console.log('No stored city found');
            }

            // 获取新城市
            const city = await GetCurrentMovieCity(getPositionApi.data as PositionType);

            // 存储城市
            if (city) {
                await Taro.setStorage({ key: CITY_STORAGE_KEY, data: city });
            }

            return city;
        },
        {
            refreshDeps: [getPositionApi.data],
            ready: !!getPositionApi.data && initReady,
            onError: () => {
                Taro.removeStorage({ key: CITY_STORAGE_KEY });
            }
        }
    );

    const { awaitAsync: awaitMovieLocation } = useAwaitAsync<City.List | null>(
        getCurrentMovieCityApi.data,
        (data) => data !== undefined || getPositionApi.data === false
    );

    // 清除位置和城市存储
    const clearLocationStorage = async () => {
        if (isH5) {
            try {
                sessionStorage.removeItem(POSITION_STORAGE_KEY);
                sessionStorage.removeItem(CITY_STORAGE_KEY);
            } catch (error) {
                console.error('Failed to clear sessionStorage', error);
            }
        }
        getPositionApi.mutate(defaultPosition);
        getCurrentMovieCityApi.mutate(null);
    };

    // 手动设置位置 - 只在H5环境下存储到sessionStorage
    const setPosition = async (position: PositionType) => {
        if (isH5) {
            try {
                sessionStorage.setItem(POSITION_STORAGE_KEY, JSON.stringify(position));
            } catch (error) {
                console.error('Failed to store position in sessionStorage', error);
            }
        }
        getPositionApi.mutate(position);
    };

    // 添加等待初始化完成的方法
    const awaitInitialized = async () => {
        if (isReady) return;
        return new Promise<void>((resolve) => {
            const check = () => {
                if (isReady) {
                    resolve();
                } else {
                    setTimeout(check, 50);
                }
            };
            check();
        });
    };

    return {
        refresh: () => {
            clearLocationStorage();
            getPositionApi.run();
        },
        position: getPositionApi.data,
        awaitPosition,
        loading: getPositionApi.loading,
        movieLocation: getCurrentMovieCityApi.data,
        setMovieLocation: (city: City.List) => {
            if (isH5) {
                try {
                    sessionStorage.setItem(CITY_STORAGE_KEY, JSON.stringify(city));
                } catch (error) {
                    console.error('Failed to store city in sessionStorage', error);
                }
            }
            getCurrentMovieCityApi.mutate(city);
        },
        awaitMovieLocation,
        clearLocationStorage,
        setPosition,
        isReady,
        awaitInitialized,
    };
});
